home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Kit PC World De Ampliacion De Windows 95
/
Kit PC World de ampliacion de Windows 95.iso
/
internet
/
sweeper
/
samples
/
olecon~1
/
controls
/
webbit~1
/
webbit~2.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1995-12-05
|
21KB
|
839 lines
//=--------------------------------------------------------------------------=
// WebBitmapCtl.Cpp
//=--------------------------------------------------------------------------=
// Copyright 1995 Microsoft Corporation. All Rights Reserved.
//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//=--------------------------------------------------------------------------=
//
//
//
#include "IPServer.H"
#include "Guids.H"
#include "LocalObj.H"
#include "Util.H"
#include "Globals.H"
#include "Resource.H"
#include "WebBitmapCtl.H"
// for ASSERT and FAIL
//
SZTHISFILE
WCHAR wszBitmap [] = L"Bitmap";
//=--------------------------------------------------------------------------=
// all the events in this control
//
// TODO: add events here ...
//
//=--------------------------------------------------------------------------=
// array describing all of our property pages. these clsids are typically
// in guids.h
//
// TODO: add any additional property page guids here ...
//
const GUID *rgWebBitmapPropPages [] = {
&CLSID_WebBitmapGeneralPage
};
//=--------------------------------------------------------------------------=
// Custum Verb information
//
// TODO: add any custom verbs here in an array, using the VERBINFO structure.
// then mark the controld def'n in WebBitmapCtl.H with
// this verb array
//
//=--------------------------------------------------------------------------=
// CWebBitmapControl::Create
//=--------------------------------------------------------------------------=
// global static function that creates an instance of the control an returns
// an IUnknown pointer for it.
//
// Parameters:
// IUnknown * - [in] controlling unknown for aggregation
//
// Output:
// IUnknown * - new object.
//
// Notes:
//
IUnknown *CWebBitmapControl::Create
(
IUnknown *pUnkOuter
)
{
// make sure we return the private unknown so that we support aggegation
// correctly!
//
CWebBitmapControl *pNew = new CWebBitmapControl(pUnkOuter);
return pNew->PrivateUnknown();
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::CWebBitmapControl
//=--------------------------------------------------------------------------=
// "Being born is like being kidnapped. And then sold into slavery."
// - andy warhol (1928 - 87)
//
// Parameters:
// IUnknown * - [in]
//
// Notes:
//
#pragma warning(disable:4355) // using 'this' in constructor
CWebBitmapControl::CWebBitmapControl
(
IUnknown *pUnkOuter
)
: CInternetControl(pUnkOuter, OBJECT_TYPE_CTLWEBBITMAP, (IDispatch *)this)
{
m_bmpPath = 0;
m_dib = 0;
m_dibFile = 0;
m_state = bdsNoBitsYet;
}
#pragma warning(default:4355) // using 'this' in constructor
//=--------------------------------------------------------------------------=
// CWebBitmapControl::~CWebBitmapControl
//=--------------------------------------------------------------------------=
// "We all labour against our own cure, for death is the cure of all diseases"
// - Sir Thomas Browne (1605 - 82)
//
// Notes:
//
CWebBitmapControl::~CWebBitmapControl ()
{
if(m_bmpPath)
delete m_bmpPath;
if( m_dibFile )
delete m_dibFile;
if( m_dib )
delete m_dib;
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl:RegisterClassData
//=--------------------------------------------------------------------------=
// register the window class information for your control here.
// this information will automatically get cleaned up for you on DLL shutdown.
//
// Output:
// BOOL - FALSE means fatal error.
//
// Notes:
//
BOOL CWebBitmapControl::RegisterClassData()
{
WNDCLASS wndclass;
// TODO: register any additional information you find interesting here.
// this method is only called once for each type of control
//
memset(&wndclass, 0, sizeof(WNDCLASS));
wndclass.style = CS_VREDRAW | CS_HREDRAW | CS_DBLCLKS | CS_OWNDC;
wndclass.lpfnWndProc = COleControl::ControlWindowProc;
wndclass.hInstance = g_hInstance;
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wndclass.lpszClassName = WNDCLASSNAMEOFCONTROL(OBJECT_TYPE_CTLWEBBITMAP);
return RegisterClass(&wndclass);
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::BeforeCreateWindow
//=--------------------------------------------------------------------------=
// called just before the window is created. Great place to set up the
// window title, etc, so that they're passed in to the call to CreateWindowEx.
// speeds things up slightly.
//
// Notes:
//
void CWebBitmapControl::BeforeCreateWindow()
{
}
void CWebBitmapControl::AfterCreateWindow()
{
m_dc = ::GetDC(m_hwnd);
HPALETTE hpal = ::CreateHalftonePalette(m_dc);
::SelectPalette(m_dc, hpal, FALSE);
UpdateBitmap();
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::InternalQueryInterface
//=--------------------------------------------------------------------------=
// qi for things only we support.
//
// Parameters:
// Parameters:
// REFIID - [in] interface they want
// void ** - [out] where they want to put the resulting object ptr.
//
// Output:
// HRESULT - S_OK, E_NOINTERFACE
//
// Notes:
//
HRESULT CWebBitmapControl::InternalQueryInterface
(
REFIID riid,
void **ppvObjOut
)
{
IUnknown *pUnk;
*ppvObjOut = NULL;
// TODO: if you want to support any additional interrfaces, then you should
// indicate that here. never forget to call COleControl's version in the
// case where you don't support the given interface.
//
if (DO_GUIDS_MATCH(riid, IID_IWebBitmap)) {
pUnk = (IUnknown *)(IWebBitmap *)this;
} else{
return COleControl::InternalQueryInterface(riid, ppvObjOut);
}
pUnk->AddRef();
*ppvObjOut = (void *)pUnk;
return S_OK;
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::LoadTextState
//=--------------------------------------------------------------------------=
// load in our text state for this control.
//
// Parameters:
// IPropertyBag * - [in] property bag to read from
// IErrorLog * - [in] errorlog object to use with proeprty bag
//
// Output:
// HRESULT
//
// Notes:
// - NOTE: if you have a binary object, then you should pass an unknown
// pointer to the property bag, and it will QI it for IPersistStream, and
// get said object to do a Load()
//
STDMETHODIMP CWebBitmapControl::LoadTextState
(
IPropertyBag *pPropertyBag,
IErrorLog *pErrorLog
)
{
VARIANT v;
VariantInit(&v);
v.vt = VT_BSTR;
v.bstrVal = NULL;
HRESULT hr = S_OK;
// try to load in the property. if we can't get it, then leave
// things at their default.
//
pPropertyBag->Read(::wszBitmap, &v, pErrorLog);
if (v.bstrVal) {
MAKE_ANSIPTR_FROMWIDE(psz, v.bstrVal);
hr = SetBmpPath(psz);
VariantClear(&v);
}
return hr;
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::LoadBinaryState
//=--------------------------------------------------------------------------=
// loads in our binary state using streams.
//
// Parameters:
// IStream * - [in] stream to write to.
//
// Output:
// HRESULT
//
// Notes:
//
const DWORD STREAMHDR_MAGIC = 12345678L;
STDMETHODIMP CWebBitmapControl::LoadBinaryState
(
IStream *pStream
)
{
DWORD sh;
HRESULT hr;
// first read in the streamhdr, and make sure we like what we're getting
//
hr = pStream->Read(&sh, sizeof(sh), NULL);
RETURN_ON_FAILURE(hr);
// sanity check
//
if (sh != STREAMHDR_MAGIC )
return E_UNEXPECTED;
return(SetBmpPath(pStream));
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::SaveTextState
//=--------------------------------------------------------------------------=
// saves out the text state for this control using a property bag.
//
// Parameters:
// IPropertyBag * - [in] the property bag with which to work.
// BOOL - [in] if TRUE, then write out ALL properties, even
// if they're their the default value ...
//
// Output:
// HRESULT
//
// Notes:
//
STDMETHODIMP CWebBitmapControl::SaveTextState
(
IPropertyBag *pPropertyBag,
BOOL fWriteDefaults
)
{
HRESULT hr;
VARIANT v;
v.vt = VT_BSTR;
v.bstrVal = BSTRFROMANSI(m_bmpPath);
RETURN_ON_NULLALLOC(v.bstrVal);
// this control currently only persists out the caption property
//
hr = pPropertyBag->Write(::wszBitmap, &v);
VariantClear(&v);
return hr;}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::SaveBinaryState
//=--------------------------------------------------------------------------=
// save out the binary state for this control, using the given IStream object.
//
// Parameters:
// IStream * - [in] save to which you should save.
//
// Output:
// HRESULT
//
// Notes:
// - it is important that you seek to the end of where you saved your
// properties when you're done with the IStream.
//
STDMETHODIMP CWebBitmapControl::SaveBinaryState
(
IStream *pStream
)
{
DWORD sh = STREAMHDR_MAGIC;
HRESULT hr;
// write out the stream hdr.
//
hr = pStream->Write(&sh, sizeof(sh), NULL);
RETURN_ON_FAILURE(hr);
// write out he control state information
//
DWORD dw = m_bmpPath ? lstrlen(m_bmpPath) : 0;
hr = pStream->Write(&dw,sizeof(dw),0);
RETURN_ON_FAILURE(hr);
if( dw )
hr = pStream->Write(m_bmpPath,dw+1,0);
return hr;}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::OnDraw
//=--------------------------------------------------------------------------=
// "I don't very much enjoy looking at paintings in general. i know too
// much about them. i take them apart."
// - georgia o'keeffe (1887-1986)
//
// Parameters:
// HDC - [in] HDC to draw to
// LPCRECTL - [in] rect we're drawing to
// LPCRECTL - [in] window extent and origin for meta-files
// HDC - [in] HIC for target device
//
// Output:
// HRESULT
//
// Notes:
//
HRESULT CWebBitmapControl::OnDraw
(
HDC hdcDraw,
LPCRECTL prcBounds,
LPCRECTL prcWBounds,
HDC hicTargetDevice
)
{
if(m_dib)
{
if( hdcDraw != m_dc )
{
HPALETTE hpal = ::CreateHalftonePalette(hdcDraw);
::SelectPalette(hdcDraw, hpal, FALSE);
}
::RealizePalette(hdcDraw);
m_dib->PaintTo(hdcDraw,prcBounds->left,prcBounds->top);
}
return S_OK;
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::OnProgress
//=--------------------------------------------------------------------------=
//
// Parameters:
// DISPID propId - [in] Same dispId that was passed into SetupDownload
// ULONG progress - [in] Size downlaoded so far
// ULONG themax - [in] Overall size of object being downloaded
// ULONG statusFlag - [in] Flags according
// LPCWSTR statusStr - [in] Readable version of status
//
// Notes:
//
HRESULT CWebBitmapControl::OnProgress
(
DISPID propId,
ULONG progress,
ULONG themax,
ULONG statusFlag,
LPCWSTR statusString
)
{
// TODO: put custom progress UI notification code here. The default action
// (shown below) is to fire an OnProgress event to the host
return(FireProgress(themax ? (progress * 100)/themax : 0));
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::WindowProc
//=--------------------------------------------------------------------------=
// window procedure for this control. nothing terribly exciting.
//
// Parameters:
// see win32sdk on window procs.
//
// Notes:
//
LRESULT CWebBitmapControl::WindowProc
(
HWND hwnd,
UINT msg,
WPARAM wParam,
LPARAM lParam
)
{
// TODO: handle any messages here, like in a normal window
// proc. note that for special keys, you'll want to override and
// implement OnSpecialKey.
//
return DefWindowProc(hwnd, msg, wParam, lParam);
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::AboutBox
//=--------------------------------------------------------------------------=
// prints up an about box. fweeeee.
//
// Notes:
//
void CWebBitmapControl::AboutBox
(
void
)
{
// TODO: Ideally, one would use DialogBox, and some sort of Dialog Box here if
// they wanted a slightly more interesting About Box ... you should
// still call ModalDialog first, however.
//
ModalDialog(TRUE);
MessageBox(NULL, "This is My Control", "About WebBitmap", MB_OK | MB_TASKMODAL);
ModalDialog(FALSE);
}
STDMETHODIMP CWebBitmapControl::get_ReadyState(long * thestate)
{
CHECK_POINTER(thestate);
*thestate = m_readyState;
return(NOERROR);
}
STDMETHODIMP CWebBitmapControl::get_Bitmap(OLE_DATAPATH * path)
{
CHECK_POINTER(path);
// Actually we need to be accepting (happily IMoniker objects)
path->vt = VT_BSTR;
BSTR * pbstrPath = &path->bstrVal;
*pbstrPath = (m_bmpPath && *m_bmpPath) ? BSTRFROMANSI(m_bmpPath) : SysAllocString(L"");
return (*pbstrPath) ? S_OK : E_OUTOFMEMORY;
}
STDMETHODIMP CWebBitmapControl::put_Bitmap(OLE_DATAPATH path)
{
// NOTE: We should reference and IMoniker*!!
if( path.vt != VT_BSTR )
return(E_UNEXPECTED);
BSTR & bstrPath = path.bstrVal;
// get an ANSI pointer, so we can stuff it in our local buffer for captions!
//
MAKE_ANSIPTR_FROMWIDE(pszPath, bstrPath);
HRESULT hr = SetBmpPath(pszPath);
// update anybody who cares about property changes and mark ourselves
// as dirty
//
PropertyChanged(DISPID_BMPPATH);
m_fDirty = TRUE;
return hr;
}
STDMETHODIMP CWebBitmapControl::Scramble()
{
HRESULT hr;
if( m_dib && (m_readyState == READYSTATE_COMPLETE) )
{
unsigned char * p = m_dib->Base();
DWORD dw = m_dib->ImageSize();
for( DWORD i = 0; i < dw; i+=3,p+=3 )
*p ^= 0x55;
InvalidateControl(0);
hr = S_OK;
}
else
{
hr = E_FAIL; // E_PENDING;
}
return(hr);
}
HRESULT CWebBitmapControl::SetBmpPath(const char *psz)
{
// if it hasn't changed, don't waste any time.
//
if (psz && m_bmpPath )
{
CHECK_POINTER(psz);
if( !lstrcmp(m_bmpPath, psz) )
return S_OK;
}
if( m_bmpPath )
delete m_bmpPath;
if(!psz)
{
m_bmpPath = 0;
return(S_OK);
}
CHECK_POINTER(psz);
if( !*psz )
{
m_bmpPath = 0;
return(S_OK);
}
DWORD dw = lstrlen(psz);
m_bmpPath = new char[dw + 1];
if( !m_bmpPath )
{
FAIL("No memory");
return(E_OUTOFMEMORY);
}
lstrcpy(m_bmpPath, psz);
UpdateBitmap();
return(S_OK);
}
HRESULT CWebBitmapControl::SetBmpPath(IStream * strm)
{
CHECK_POINTER(strm);
char * tmp = 0;
if( m_bmpPath )
delete m_bmpPath;
DWORD dw;
HRESULT hr = strm->Read(&dw,sizeof(dw),0);
if( SUCCEEDED(hr) )
{
if( !dw )
{
hr = S_OK;
}
else
{
tmp = new char[dw+1];
if( !tmp )
{
FAIL("No memory");
hr = E_OUTOFMEMORY;
}
else
{
hr = strm->Read(tmp,dw+1,0);
}
}
}
// if it hasn't changed, don't waste any time.
//
if ((!tmp && !m_bmpPath) || !lstrcmp(m_bmpPath, tmp))
return S_OK;
if( m_bmpPath )
delete m_bmpPath;
m_bmpPath = tmp;
UpdateBitmap();
return(hr);
}
HRESULT CWebBitmapControl::UpdateBitmap()
{
if( !m_hwnd )
return(S_OK);
if( !m_bmpPath )
return(S_OK);
FireReadyStateChange(READYSTATE_INTERACTIVE);
return( SetupDownload(OLESTRFROMANSI(m_bmpPath),DISPID_BMPPATH) );
}
//=--------------------------------------------------------------------------=
// CWebBitmapControl::OnData
//=--------------------------------------------------------------------------=
//
// Parameters:
// DISPID propId - [in] Same dispId that was passed into SetupDownload
// DWORD grfBSCF - [in] Notification flags ("URL Moniker" specification)
// IStream * strm - [in] Stream to read data from
// DWORD dwSize - [in] Overall size available so far
//
//
// Notes: This is the class that is monitering and interpreting the bits that
// are being downloaded. The methods in class inherited from IBindStatusCallback
// are only called during 'DispatchMessage' calls from the main applications loop.
// This impelmentation maintains a state machine for the bits as they arrive:
//
// Initial state: No bits have been seen yet
//
// Have BITMAPFILEHEADER We now have this structure. At this point there is
// enough information to calculate the following values:
// - The file is actually a Windows BMP file
// - The size of the entire image
// - This size of the BITMAPINFO structure
//
// Have BITMAPINFO We now have enough information to call
// CreateDibSection! That function will return a
// a buffer it allocated.
//
// Getting BITS At this point the bits are arriving and all we
// have to do is strm->Read the bits directly into
// buffer returned from the step above and notify
// our view sink that we need refreshing.
//
// BITS are done (nothing to do!?)
//
HRESULT CWebBitmapControl::OnData
(
DISPID propId,
DWORD grfBSCF,
IStream * strm,
DWORD dwSize
)
{
HRESULT hr = NOERROR;
switch(m_state)
{
case bdsNoBitsYet:
{
if( dwSize >= sizeof(BITMAPFILEHEADER) )
{
if( m_dibFile )
delete m_dibFile;
m_dibFile = new CDibFile;
if( !m_dibFile )
{
hr = E_OUTOFMEMORY;
break;
}
hr = m_dibFile->GetFileHeader(strm);
if( FAILED(hr) )
break;
m_state = bdsGotFileHeader;
// now FALL THRU!
}
else
{
break;
}
}
case bdsGotFileHeader:
{
if( dwSize >= (m_dibFile->HeaderSize() + sizeof(BITMAPFILEHEADER)) )
{
if( m_dibFile )
hr = m_dibFile->GetInfoHeader(strm);
else
hr = E_OUTOFMEMORY;
if( FAILED(hr) )
break;
if( m_dib )
delete m_dib;
m_dib = new CDibSection;
if( !m_dib )
{
hr = E_OUTOFMEMORY;
break;
}
m_dib->Setup(m_dc);
hr = m_dib->Create(*m_dibFile);
if( FAILED(hr) )
break;
m_dib->ImageSize( m_dibFile->CalcImageSize() );
m_state = bdsGotBitmapInfo;
// FALL THRU!
}
else
{
break;
}
}
case bdsGotBitmapInfo:
{
SIZEL sz;
m_dib->GetSize(sz);
SetControlSize(&sz);
m_oldSize = (m_dibFile->HeaderSize() + sizeof(BITMAPFILEHEADER));
delete m_dibFile;
m_dibFile = 0;
m_state = bdsGettingBits;
// FALL THRU
}
case bdsGettingBits:
{
if( dwSize > m_oldSize )
{
hr = m_dib->ReadFrom( strm, dwSize - m_oldSize );
if( FAILED(hr) )
break;
::RealizePalette(m_dc);
m_dib->PaintTo(m_dc);
m_oldSize = dwSize;
}
if( grfBSCF & BSCF_LASTDATANOTIFICATION )
m_state = bdsBitsAreDone;
else
break;
}
case bdsBitsAreDone:
{
m_state = bdsNoBitsYet;
FireReadyStateChange(READYSTATE_COMPLETE);
break;
}
}
return(hr);
}